/*
 Trabajo Practico 3 Ejercicio 1
 Segunda Entrega

 - Integrantes:
	- Martinez, Guillermo	DNI: 34510461
	- Barrera, Lourdes		DNI: 33306634
	- Reyes, Leandro		DNI: 34213699
	- Rodriguez, Lucas		DNI: 34265017
*/

#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>

void CreaSemaforos();
void CreaBanco();
void CerrarSemaforos();
void CierraBanco();
void RealizaTramite();

sem_t *MutexCaja = NULL, *MutexTramiteFinalizado = NULL;
sem_t *HayClientes = NULL, *HayVips = NULL;
sem_t *PasaComunes = NULL,*PasaVips = NULL,  *BancoAbierto = NULL;

char _MutexCaja[] = "SMutexCaja";
char _MutexTramiteFinalizado [] = "SMutexTramiteFinalizado";
char _HayClientes [] = "SHayClientes";
char _HayVips [] = "SHayVIps";
char _PasaComunes [] = "SPasaComunes";
char _PasaVips [] = "SPasaVips";
char _BancoAbierto [] = "SBancoAbierto";

int SoyVip = 0;
int Tiempo;

void main(int argc, char *argv[])
{
	int val;

	CreaBanco();

	sem_getvalue(BancoAbierto, &val);
	
	if(val!=0)
	{	
		int j;
		
		// Ignoro todas las señales
		for(j=1;j<32;j++)
			if(j!= 9  && j != 19)
				signal(j, SIG_IGN);
	    
		if(argc > 3 || argc == 1)
		{
			printf("Uso: %s TIEMPO_DE_TRAMITE [Tipo Cliente (V/v)] \n", argv[0]);
			exit(-1);
		}
		
		Tiempo = atoi(argv[1]);
		
		if((argc == 3) &&( (strcmp (argv[2],"v") == 0 ) || (strcmp (argv[2],"V") == 0 )))
			SoyVip = 1;

		CreaSemaforos();

		if(SoyVip)	
			sem_post(HayVips);

		sem_post(HayClientes);

		if(SoyVip)
		{
			printf("Cliente  %d > Cliente VIP %d \n", getpid(), getpid());
			sem_wait(PasaVips);
		}
		
		else
		{
			printf("Cliente  %d > Cliente %d \n", getpid(), getpid());
			sem_wait(PasaComunes);
		}

		sem_wait(MutexCaja);
		RealizaTramite();
		sem_post(MutexCaja);

		sem_post(MutexTramiteFinalizado);
		printf("Cliente %d > Saliendo\n", getpid());
	}
	
	else
		CierraBanco();	
}	

void CreaBanco()
{
	if((BancoAbierto = sem_open(_BancoAbierto,0)) == SEM_FAILED) 
	{
		printf("Cliente %d > El banco está cerrado, vuelva más tarde\n", getpid());
		sem_close(BancoAbierto);	
		exit(-1);
	}

	return;		
}

void CierraBanco()
{
	printf("Cliente %d > El banco está cerrado, vuelva más tarde\n", getpid());
	sem_close(BancoAbierto);	
}

void CreaSemaforos()
{
	if((MutexCaja = sem_open(_MutexCaja,0)) == SEM_FAILED)
		goto Error;
		
	if((MutexTramiteFinalizado = sem_open(_MutexTramiteFinalizado,0)) == SEM_FAILED) 
		goto Error;
		
	if((HayClientes = sem_open(_HayClientes,0)) == SEM_FAILED) 
		goto Error;
		
	if((HayVips = sem_open(_HayVips,0)) == SEM_FAILED)
		goto Error;		
	
	if((PasaComunes = sem_open(_PasaComunes,0)) == SEM_FAILED)
		goto Error;
		
	if((PasaVips = sem_open(_PasaVips,0)) == SEM_FAILED) 
		goto Error;

	return;
	
Error:
		printf("Cliente %d > El banco está cerrado, vuelva más tarde\n", getpid());
		CerrarSemaforos();
		exit(-1);
}

void CerrarSemaforos()
{
	sem_close(MutexCaja);
	sem_close(MutexTramiteFinalizado);
	sem_close(HayClientes);
	sem_close(HayVips);
	sem_close(PasaComunes);
	sem_close(PasaVips);
}
	
void RealizaTramite()
{
	printf("Cliente %d > Realizando trámite de %d segundos...\n", getpid(), Tiempo);
	sleep(Tiempo);
}
